// 前端计算器逻辑单元测试
// 模拟ClientCalculator组件的计算逻辑

const { createClient } = require("@connectrpc/connect");
const { createConnectTransport } = require("@connectrpc/connect-web");

// 模拟后端响应
const mockCalculate = (prior, post, op) => {
  let result;
  switch (op) {
    case 0: result = prior + post; break;
    case 1: result = prior - post; break;
    case 2: result = prior * post; break;
    case 3: 
      if (post === 0) throw new Error("Division by zero");
      result = prior / post; 
      break;
    default: throw new Error("Invalid operation");
  }
  return { result };
};

// 计算器状态模拟
class CalculatorState {
  constructor() {
    this.board = 0;
    this.op = null;
    this.isNegative = 0;
    this.isErr = false;
    this.opReq = {
      prior: null,
      post: null,
      op: null
    };
  }

  // 数字输入逻辑
  push(n) {
    if (this.isErr) {
      this.isErr = false;
    }
    
    // 问题1：当有运算符且输入数字时的逻辑有问题
    if (this.op !== null && n !== -1 && n !== -2) {
      if (this.opReq.post !== null) {
        this.calc();
        this.opReq.post = null;
      }
      this.opReq.prior = this.board * (this.isNegative === 1 ? -1 : 1);
      this.isNegative = 0;
      this.board = n;  // 问题：这里应该重置而不是直接设置为n
      this.op = null;
      return;
    }
    
    if (this.board >= 99999999 && n !== -1 && n !== -2) {
      return;
    }
    
    switch (n) {
      case 0:
        if (this.board === 0) {
          this.board = n;
          return;
        }
        this.board = this.board * 10 + n;
        break;
      case -1: // 清除
        this.opReq = { prior: null, post: null, op: null };
        this.board = 0;
        this.op = null;
        return;
      case -2: // 退格
        this.board = Math.floor(this.board / 10);
        if (this.board === 0 && this.isNegative === 1) {
          this.isNegative = 0;
        }
        return;
      default:
        this.board = this.board * 10 + n;
    }
  }

  // 运算符按下
  pressOp(pop) {
    if (pop === this.op) {
      this.op = null;
      return;
    }
    this.op = pop;
    this.opReq.op = pop;
  }

  // 计算逻辑
  calc() {
    if (this.opReq.post === null) {
      this.opReq.post = this.board * (this.isNegative === 1 ? -1 : 1);
      this.isNegative = 0;
    }
    
    try {
      const res = mockCalculate(this.opReq.prior, this.opReq.post, this.opReq.op);
      if (res.result === null) {
        this.board = 0;
        return;
      }
      this.board = Math.abs(res.result);
      if (res.result < 0) {
        this.isNegative = 1;
      }
      this.op = null;
      this.opReq.prior = res.result;  // 问题2：这里为连续计算做准备
    } catch (error) {
      this.isErr = true;
      this.board = 0;
    }
  }
}

// 单元测试
function runTests() {
  console.log("🧪 开始前端计算器单元测试");
  console.log("=" * 50);

  let testsPassed = 0;
  let totalTests = 0;

  function test(name, testFn) {
    totalTests++;
    try {
      testFn();
      console.log(`✅ ${name}`);
      testsPassed++;
    } catch (error) {
      console.log(`❌ ${name}: ${error.message}`);
    }
  }

  // 基础运算测试
  test("基础加法: 5 + 3 = 8", () => {
    const calc = new CalculatorState();
    calc.push(5);
    calc.pressOp(0); // +
    calc.push(3);
    calc.calc();
    if (calc.board !== 8) throw new Error(`Expected 8, got ${calc.board}`);
  });

  test("基础减法: 10 - 4 = 6", () => {
    const calc = new CalculatorState();
    calc.push(1); calc.push(0); // 10
    calc.pressOp(1); // -
    calc.push(4);
    calc.calc();
    if (calc.board !== 6) throw new Error(`Expected 6, got ${calc.board}`);
  });

  test("基础乘法: 6 × 7 = 42", () => {
    const calc = new CalculatorState();
    calc.push(6);
    calc.pressOp(2); // ×
    calc.push(7);
    calc.calc();
    if (calc.board !== 42) throw new Error(`Expected 42, got ${calc.board}`);
  });

  test("基础除法: 20 ÷ 4 = 5", () => {
    const calc = new CalculatorState();
    calc.push(2); calc.push(0); // 20
    calc.pressOp(3); // ÷
    calc.push(4);
    calc.calc();
    if (calc.board !== 5) throw new Error(`Expected 5, got ${calc.board}`);
  });

  // 连续运算测试（问题场景）
  test("连续运算: 1 + 1 = 2, 然后 × 3 = 6", () => {
    const calc = new CalculatorState();
    // 1 + 1 = 2
    calc.push(1);
    calc.pressOp(0); // +
    calc.push(1);
    calc.calc();
    console.log(`第一步结果: ${calc.board}, opReq.prior: ${calc.opReq.prior}`);
    
    // 然后 × 3
    calc.pressOp(2); // ×
    calc.push(3);
    calc.calc();
    console.log(`最终结果: ${calc.board}, opReq.prior: ${calc.opReq.prior}`);
    
    if (calc.board !== 6) throw new Error(`Expected 6, got ${calc.board}`);
  });

  test("复杂连续运算: 2 × 3 = 6, 然后 + 4 = 10", () => {
    const calc = new CalculatorState();
    // 2 × 3 = 6
    calc.push(2);
    calc.pressOp(2); // ×
    calc.push(3);
    calc.calc();
    
    // 然后 + 4 = 10
    calc.pressOp(0); // +
    calc.push(4);
    calc.calc();
    
    if (calc.board !== 10) throw new Error(`Expected 10, got ${calc.board}`);
  });

  test("三步连续运算: 5 + 5 = 10, × 2 = 20, ÷ 4 = 5", () => {
    const calc = new CalculatorState();
    // 5 + 5 = 10
    calc.push(5);
    calc.pressOp(0); // +
    calc.push(5);
    calc.calc();
    
    // × 2 = 20
    calc.pressOp(2); // ×
    calc.push(2);
    calc.calc();
    
    // ÷ 4 = 5
    calc.pressOp(3); // ÷
    calc.push(4);
    calc.calc();
    
    if (calc.board !== 5) throw new Error(`Expected 5, got ${calc.board}`);
  });

  // 错误处理测试
  test("除零错误处理", () => {
    const calc = new CalculatorState();
    calc.push(5);
    calc.pressOp(3); // ÷
    calc.push(0);
    calc.calc();
    if (!calc.isErr) throw new Error("Expected error flag to be set");
  });

  // 清除功能测试
  test("清除功能", () => {
    const calc = new CalculatorState();
    calc.push(1); calc.push(2); calc.push(3);
    calc.pressOp(0);
    calc.push(-1); // 清除
    if (calc.board !== 0 || calc.op !== null) {
      throw new Error("Clear function failed");
    }
  });

  console.log("=" * 50);
  console.log(`📊 测试结果: ${testsPassed}/${totalTests} 通过`);
  
  if (testsPassed < totalTests) {
    console.log("\n🔍 发现的主要问题:");
    console.log("1. 连续运算时状态管理有问题");
    console.log("2. 数字输入后运算符状态重置逻辑错误");
    console.log("3. opReq状态在连续计算中没有正确维护");
  }
  
  return testsPassed === totalTests;
}

// 运行测试
runTests();